<?php
namespace PsiFramework\Applications\AlloMediaPortal\Classes\DAO;

import("Classes.DAO.AbstractDAO");
import("Applications.AlloMediaPortal.Classes.Model.AlloMediaEntry");

use \PsiFramework\Classes\DAO\AbstractDAO;
use \PsiFramework\Classes\Model\Object;
use \PsiFramework\Classes\Model\ModelInterface\IPrimitiveObject;
use \PsiFramework\Classes\Factory\DAOFactory;
use \PsiFramework\Classes\Util\Database\Builder\QueryBuilder;
use \PsiFramework\Classes\Util\Database\Query\SqlColumn;
use \PsiFramework\Classes\Util\Database\Query\SqlFunction;
use \PsiFramework\Classes\Util\Database\Query\SqlJoin;
use \PsiFramework\Classes\Util\Database\Query\SqlOn;
use \PsiFramework\Classes\Util\Database\Query\SqlOperation;
use \PsiFramework\Classes\Util\Database\Query\SqlTable;
use \PsiFramework\Classes\Util\Database\Query\SqlValue;
use \PsiFramework\Classes\Util\Object\Date;
use \PsiFramework\Classes\Util\Parameters\ObjectParameters;
use \PsiFramework\Applications\AlloMediaPortal\Classes\Model\ResponseId;
use \PsiFramework\Applications\AlloMediaPortal\Classes\Model\AlloMediaEntry;
use \PsiFramework\Plugins\Form\Classes\DAO\FormResponseDAO;
use \PsiFramework\Plugins\Form\Classes\Util\Json\Elements\JsonFormInput;
use \PsiFramework\Plugins\Form\Classes\Util\Json\Elements\JsonFormText;
use \PsiFramework\Plugins\Form\Classes\Util\Json\Elements\JsonFormTitle;

/**
 * AlloMedia
 * Portail des professionnels
 *
 * @author Rémi San
 * @version beta
 */

/**
 * The AlloMediaEntryDAO is the Data Access Object for the class AlloMediaEntry
 *
 * @package DAO
 */
class AlloMediaEntryDAO extends AbstractDAO
{

    protected static $_singleton = null;

    public function save(
        Object &$object,
        /*bool*/ $performTransaction=true,
        /*bool*/ $checkSecurity=true
    )
    {

        if ($performTransaction) {
        	$this->_database->startTransaction();
        }

        $ok = parent::save($object, false, $checkSecurity);

        if ($ok) {
            $category = $object->getCategory();
            if (!is_null($category)) {
                $profile = $category->getProfile();
                if (!is_null($profile)) {
                    $parts = $profile->getParts();
                    if (!is_null($parts)) {
                        $responseIdDao = DAOFactory::getDAO("ResponseId");
                        $responseIds = array();
                        foreach ($parts as $part) {
                            $theme = $part->getTheme();
                            $responseId
                                = $responseIdDao->retrieveByEntryAndTheme(
                                    $object,
                                    $theme
                                );

                            if (is_null($responseId)) {
                                $responseId = new ResponseId();
                                $responseId->setEntry($object);
                                $responseId->setTheme($theme);

                                $responseIdDao->save(
                                    $responseId,
                                    false,
                                    $checkSecurity
                                );
                                $responseIds[] = $responseId;
                            }
                        }
                        $object->setResponseIds($responseIds);
                    }
                }
            }
        }

        if ($performTransaction) {
            if ($ok) {
                $this->_database->commit();
            } else {
                $this->_database->rollback();
            }
        }

        return $ok ;
    }

    public function delete(
        Object &$object,
        /*bool*/ $performTransaction=true,
        /*bool*/ $checkSecurity=true)
    {

        $siteMembershipDao = DAOFactory::getDAO('SiteMembership');
        $responseIdDao = DAOFactory::getDAO('ResponseId');

        if ($performTransaction) {
        	$this->_database->startTransaction();
        }

        $ok = true ;
        $sites = $object->getSites();
        foreach ($sites as $siteMembership) {
            $ok = $siteMembershipDao->delete(
                $siteMembership,
                false,
                $checkSecurity
            );
            if (!$ok) {
            	break;
            }
        }

        if ($ok) {
            $responseIds = $object->getResponseIds();
            foreach ($responseIds as $responseId) {
                $ok = $responseIdDao->delete(
                    $responseId,
                    false,
                    $checkSecurity
                );
                if (!$ok) {
                	break;
                }
            }
        }

        if ($ok) {
        	$ok = parent::delete($object, false, $checkSecurity);
        }

        if ($performTransaction) {
            if ($ok) {
                $this->_database->commit();
            } else {
                $this->_database->rollback();
            }
        }

        return $ok ;
    }

    public function retrieveByResponses(
        /*AlloMediaSite*/ $site,
        /*SiteCategory*/ $category,
        /*int*/ $since,
        /*boolean*/ $checkSecurity=true
    )
    {

        $allEntries = array();

        if (is_null($site) || is_null($category)) {
        	return $allEntries ;
        }
        
        $idName = 'formResponseId';

        $date = Date::interval(Date::now(), -3600*$since);

        $profile = $category->getProfile();
        if (!is_null($profile)) {
            $parts = $profile->getParts();
            foreach ($parts as $part) {
                $form = $part->getTheme();
                $formResponseParameters = $form->getResponseParameters();

                $entryTable = new SqlTable('entry', 'allomediaportal', 't0');
                $siteMembershipTable
                    = new SqlTable('site_membership', 'allomediaportal', 't1');
                $responseIdTable
                    = new SqlTable('response_id', 'allomediaportal', 't2');
                $formTable = new SqlTable(
                    $formResponseParameters->getTable(),
                    $formResponseParameters->getSchema(),
                    't3'
                );

                $entryEntryId = new SqlColumn('entry_id', $entryTable);
                $siteMembershipEntryId
                    = new SqlColumn('entry_id', $siteMembershipTable);
                $responseIdEntryId
                    = new SqlColumn('entry_id', $responseIdTable);

                $responseIdResponseId
                    = new SqlColumn('response_id', $responseIdTable);
                $formResponseId
                    = new SqlColumn(
                        $formResponseParameters->getParameter($idName)->column,
                        $formTable
                    );


                $queryBuilder = new QueryBuilder();
                $queryBuilder->createSelectQuery();
                $queryBuilder->setTable($entryTable);
                $queryBuilder->addJoin(
                    new SqlJoin(
                        $siteMembershipTable,
                        new SqlOn(
                            new SqlOperation(
                                SqlOperation::$equal,
                                array($entryEntryId, $siteMembershipEntryId)
                            )
                        )
                    )
                );
                $queryBuilder->addJoin(
                    new SqlJoin(
                        $responseIdTable,
                        new SqlOn(
                            new SqlOperation(
                                SqlOperation::$equal,
                                array($entryEntryId, $responseIdEntryId)
                            )
                        )
                    )
                );
                $queryBuilder->addJoin(
                    new SqlJoin(
                        $formTable,
                        new SqlOn(
                            new SqlOperation(
                                SqlOperation::$equal,
                                array($responseIdResponseId, $formResponseId)
                            )
                        )
                    )
                );

                $distinct = new SqlFunction("DISTINCT");
                $distinct->addParameter($entryEntryId);
                $queryBuilder->addSelectColumn($distinct);
                foreach (
                    $this->_objectParameters->getParameters() as $parameter
                ) {
                    if ($parameter->name != $idName) {
                        $queryBuilder->addSelectColumn(
                            new SqlColumn($parameter->column, $entryTable)
                        );
                    }
                }

                $whereClause = new SqlOperation(SqlOperation::$and);
                $whereClause->addParameter(
                    new SqlOperation(
                        SqlOperation::$equal,
                        array(
                            new SqlColumn('category_id', $entryTable),
                            new SqlValue($category->getId())
                        )
                    )
                );
                $whereClause->addParameter(
                    new SqlOperation(
                        SqlOperation::$equal,
                        array(
                            new SqlColumn('site_id', $siteMembershipTable),
                            new SqlValue($site->getId())
                        )
                    )
                );

                $orClause = new SqlOperation(SqlOperation::$or);
                $orClause->addParameter(
                    new SqlOperation(
                        SqlOperation::$greaterThanOrEqual,
                        array(
                            new SqlColumn('modification_date', $formTable),
                            new SqlValue($date)
                        )
                    )
                );
                $orClause->addParameter(
                    new SqlOperation(
                        SqlOperation::$greaterThanOrEqual,
                        array(
                            new SqlColumn('modification_date', $entryTable),
                            new SqlValue($date)
                        )
                    )
                );

                $whereClause->addParameter($orClause);

                $queryBuilder->addWhereClause($whereClause);

                $entries = $this->processQueryBuilder($queryBuilder, $checkSecurity);
                if (!is_null($entries)) {
                    foreach ($entries as $entry) {
                        $allEntries[$entry->getId()] = $entry ;
                    }
                }
            }
        }

        return $allEntries ;
    }
    
    public static function getAsXml(Object $entry, /*int*/ $id=null, \DOMDocument $doc=null) {
        
        $responseIdDao = DAOFactory::getDAO('ResponseId');
        
        if (is_null($doc)) {
            $doc = new \DOMDocument('1.0', 'UTF-8');
            $doc->formatOutput = true;
        }
        
        $entryXml = $doc->createElement('fiche');
        
        if (!isNullOrEmptyString($id)) {
            $entryXml->setAttribute("id", $id);
        }
        
        $nameXml = $doc->createElement('nom', $entry->getName());
        $entryXml->appendChild($nameXml);
        
        $addressXml = $doc->createElement('adresse', $entry->getAddress());
        $entryXml->appendChild($addressXml);
        
        $zipXml = $doc->createElement('code_postal', $entry->getZip());
        $entryXml->appendChild($zipXml);
        
        $cityXml = $doc->createElement('ville', $entry->getCity());
        $entryXml->appendChild($cityXml);
        
        $telXml = $doc->createElement('tel', $entry->getTel());
        $entryXml->appendChild($telXml);
        
        $faxXml = $doc->createElement('fax', $entry->getFax());
        $entryXml->appendChild($faxXml);
        
        $mobileXml = $doc->createElement('mobile', $entry->getMobile());
        $entryXml->appendChild($mobileXml);
        
        $tel2Xml = $doc->createElement('tel2', $entry->getTel2());
        $entryXml->appendChild($tel2Xml);
        
        if(!is_null($entry->getCategory())){
            
            $profile = $entry->getCategory()->getProfile();
            $profile->getParts();
            $parts = $profile->sortParts();
            foreach ($parts as $part) {
            	$theme = $part->getTheme();
            	
            	$themeXml = $doc->createElement('theme');
            	$themeXml->setAttribute('name', $theme->getName());
            	$themeXml->setAttribute('title', $theme->getTitle());
            
            	$form = $theme->getStructure();
            	$responseParameters = $theme->getResponseParameters();
            
            	$responseId
            	    = $responseIdDao->retrieveByEntryAndTheme(
            			$entry,
            			$theme
            	    );
            	$responseDao
            	    = FormResponseDAO::getInstance($responseParameters);
            
            	$response = null ;
            
            	if (!is_null($responseId)) {
            
            		$response = $responseDao->retrieveByPk(
        				$responseId->getId(),
        				false,
        				true,
        				$responseId->getEntry()->getUser(),
        				$theme
            		);
            
            		if (!is_null($response)) {
            
            			$elements = $form->getElements();
            
            			if (!is_null($elements)) {
            
            				foreach ($elements as $field) {
            
            					$fieldsetElement = $doc->createElement('field');
            					$fieldsetElement->setAttribute(
        							'name',
        							$field->getName()
            					);
            
            					foreach ($field->getElements() as $element) {
            
            						$inputElement = null ;
            						
            						if ($element instanceof JsonFormInput) {
            
            							$value = null ;
            							if (!is_null($response)) {
            								$param
            								    = $responseParameters->
                    								getParameter(
                										$element->getName()
                    								);
            								if (!is_null($param)) {
            									$getter = $param->getter ;
            									$value = $response->{$getter}();
            								}
            							}
            
            							$stringValue = $value ;
            							if ($value instanceof Object) {
            								$stringValue = $value->toString();
            							} else if ($value instanceof IPrimitiveObject) {
            								$stringValue = $value->toString();
            								if (!isNullOrEmptyString($stringValue) && $element->getInputType() == 'file') {
            								    $stringValue = str_replace(getWwwDirectory().'/', '', realpath($stringValue));
            								}
            							}
            
            							$inputElement
                							= $doc->createElement('valeur', $stringValue);
                							$inputElement->setAttribute(
            									'label',
            									$element->getLabel()
            							    );
            
            							if ($element->isDisplayedAsImage()) {
            								$inputElement->setAttribute(
        										'displayAsImage',
        										'true'
            								);
            							}
            							
            						} else {
            							if ($element->isDisplayedWithValues()) {
            								$tag = null ;
            								$label = null ;
            
            								if ($element instanceof JsonFormText) {
            									$tag = 'texte' ;
            									$label = $element->getLabel();
            								} else if ($element instanceof JsonFormTitle) {
            									$tag = 'titre' ;
            									$label = $element->getLabel();
            								} else {
            									$tag = 'clear-both' ;
            								}
            
            								if (!is_null($tag)) {
            									$inputElement = $doc->createElement($tag);
            									if (!is_null($label)) {
            										$inputElement->setAttribute('label', $label);
            									}
            								}
            							}
            						}
            						
            						if (!is_null($inputElement)) {
            						    
            						    if (!isNullOrEmptyString($element->getClassName())) {
            						    	$inputElement->setAttribute('class', $element->getClassName());
            						    }
            						    
            						    if (!isNullOrEmptyString($element->getStyle())) {
            						    	$inputElement->setAttribute('style', $element->getStyle());
            						    }
            						    
            							$fieldsetElement->appendChild($inputElement);
            						}
            					}
            					
            					if (!is_null($fieldsetElement)) {
                					
                					if (!isNullOrEmptyString($field->getClass())) {
                					    $fieldsetElement->setAttribute('class', $field->getClass());
                					}
                					
                					if (!isNullOrEmptyString($field->getStyle())) {
                						$fieldsetElement->setAttribute('style', $field->getStyle());
                					}
                					
                					$themeXml->appendChild($fieldsetElement);
            					}
            				}
            			}
            		}
            	}
            
            	$entryXml->appendChild($themeXml);
            }
        }
        
        return $entryXml;
    }

    /**
     * Function to be called instead of the constructor.
     *
     * @return AlloMediaEntryDAO    instance
     */
    public static function getInstance(ObjectParameters $objectParameters)
    {

        if (self::$_singleton==null) {
            self::$_singleton = new AlloMediaEntryDAO($objectParameters);
        }

        return self::$_singleton;
    }

}
